# Define ORM classes (often called "mapped classes").

from lxml import etree

class MalformedXMLException(Exception): pass
class MappingException(Exception): pass
class AttributeValueException(Exception): pass

class Item(object):
    mapping = {}

    def loadFromXML(self, xmlStr):
        try:
            xmlTree = etree.fromstring(xmlStr)
            for key, value in self.mapping.iteritems():
                if value.has_key('obligatory') and value['obligatory']:
                    result = xmlTree.xpath(value['map'])[0]
                else:
                    result = xmlTree.xpath(value['map'])
                    if len(result)>0:
                        result = result[0]
                    else:
                        result = None
                self.__setattr__(key, result)
        except etree.XMLSyntaxError, e:
            raise MalformedXMLException(xmlStr)
        except KeyError, e:
            raise MappingException(value)
        except IndexError, e:
            raise AttributeValueException("Attribute %s marked as obligatory but was empty" % key)

    def getId(self):
        return self.id

class Project(object):
    def __init__(self, name, description, client):
        self.name = name
        self. description = description
        self.client = client

    def __repr__(self):
        return "Project('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')" % (self.id, self.name, self.description, self.client, self.start, self.end, self.created, self.updated)

class User(Item):
    def __init__(self, username="", password="", name="", last_name="", group=None, role=None):
        self.username = username
        self.password = password
        self.name = name
        self.last_name = last_name
        self.group = group
        self.role = role
        Item.__init__(self)
        self.mapping = { 'username':  {'map': '/user/username/text()', 'obligatory': True}
                        , 'password': {'map': '/user/password/text()', 'obligatory': True}
                        , 'name': {'map': '/user/name/text()'}
                        , 'last_name': {'map': '/user/last_name/text()'}
                        }

    def __repr__(self):
        return "<User('%s', '%s', '%s', '%s', '%s', '%s')>" % (self.id, self.username, self.password, self.name, self.last_name, self.created)

class ClientRequirement(object):
    def __repr__(self):
        return "CR('%s', '%s', '%s', '%s', '%s')" % (self.id, self.project_id, self.name, self.description, self.priority_id)

class Priority(object):
    def __init__(self, name, description):
        self.name = name
        self.description = description

    def __repr__(self):
        return "<Priority('%s', '%s', '%s')>" % (self.id, self.name, self.description)

class Status(object):
     def __init__(self, name, description):
        self.name = name
        self.description = description

     def __repr__(self):
         return "Status('%s', '%s', '%s')" % (self.id, self.name, self.description)

class Type(object):
    def __init__(self, name, description):
        self.name = name
        self.description = description

    def __repr__(self):
        return "Type('%s', '%s', '%s')" % (self.id, self.name, self.description)

class Impact(object):
    def __init__(self, name, description):
        self.name = name
        self.description = description

    def __repr__(self):
        return "Impact('%s', '%s', '%s')" % (self.id, self.name, self.description)

class AceptanceTest(object):
    def __init__(self, name, input, output):
        self.name = name
        self.input = input
        self.output = output

    def __repr__(self):
        return "AceptanceTest('%s', '%s', '%s', '%s')" % (self.id, self.name, self.input, self.output)

class ProductRequirement(object):
    def __init__(self, name, description):
        self.name = name
        self.description = description

    def __repr__(self):
        return "ProductRequirement('%s', '%s', '%s', '%s', '%s')" % (self.id, self.name, self.description, self.project_id, self.priority_id)

class TestCase(object):
    def __init__(self, name, description, input, output):
        self.name = name
        self.description = description
        self.input = input
        self.output = output

    def __repr__(self):
        return "TestCase('%s', '%s', '%s', '%s', '%s')" % (self.id, self.name, self.description, self.input, self.output)

class Product(object):
    def __init__(self, name, description, path, type):
        self.name = name
        self.description = description
        self.path = path
        self.type = type

    def __repr__(self):
        return "Product('%s', '%s', '%s', '%s', '%s')" % (self.id, self.name, self.description, self.path, self.type)

class CrPrAssociation(object):
    def __init__(self):
        pass

    def __repr__(self):
        return "CrPrAssociation('%s', '%s', '%s')" % (self.id, self.cr_id, self.pr_id)

class PrProdAssociation(object):
    def __repr__(self):
        return "PrProdAssociation('%s', '%s', '%s')" % (self.id, self.pr_id, self.prod_id)
